﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using NetworkUI;
using DataLayer;
using Utils;
using NetworkModel;
using AdornedControl;
using AvalonDock;
using System.Text.RegularExpressions;
using System.Threading;
using System.Windows.Threading;
namespace LuanVanProject
{
    /// <summary>
    /// Interaction logic for MindmapEditor.xaml
    /// </summary>
    public partial class MindmapEditor : Observer
    {
        bool isSummerEditor = false;

        public bool IsSummerEditor
        {
            get { return isSummerEditor; }
            set { isSummerEditor = value; }
        }
        static public DetailViewContent detailView;
        public MindMap currentMindmap;

        void Observer.Update()
        {
            this.ViewModel.PopulateData(this.ViewModel.ViewNode);
        }
        /// <summary>
        /// Convenient accessor for the view-model.
        /// </summary>
        /// 
        public MainWindowViewModel ViewModel
        {
            get
            {
                return (MainWindowViewModel)this.DataContext;
            }
        }

        public MindmapEditor()
        {
            InitializeComponent();
            //ViewModel.PopulateWithTestData();
            ViewModel.AddObserver(this);
            InitContextMenu();
        }

        public MindmapEditor(bool _isSummery)
        {
            InitializeComponent();
            //ViewModel.PopulateWithTestData();
            ViewModel.AddObserver(this);
            this.isSummerEditor = _isSummery;
            InitContextMenu();
        }

        public void InitContextMenu()
        {
            if (isSummerEditor)
            {
                (this.ContextMenu.Items[0] as MenuItem).Visibility = System.Windows.Visibility.Collapsed;
                (this.ContextMenu.Items[2] as MenuItem).Visibility = System.Windows.Visibility.Collapsed;
                (this.ContextMenu.Items[3] as MenuItem).Visibility = System.Windows.Visibility.Collapsed;
            }
            else
            {
                (this.ContextMenu.Items[5] as MenuItem).Visibility = System.Windows.Visibility.Collapsed;
            }
        }


        public void LoadData(MindMap mindMap)
        {
            ViewModel.PopulateData(mindMap);
            currentMindmap = mindMap;
        }

        public void LoadData(Node node)
        {
            ViewModel.PopulateData(node);
        }

        public NodeViewModel AddNodeToEditor(Node _node, double x, double y)
        {
            currentMindmap.RootNode.ChildrenNodeList.Add(_node);
            _node.ParentNode = currentMindmap.RootNode;
            return ViewModel.CreateNodeAt(_node, x, y);
            
        }

        public void AddNodeToEditor(Node _node, NodeViewModel _parentNode)
        {
            ViewModel.CreateNode(_node, _parentNode);

        }
        
        /// <summary>
        /// Event raised to create a new node.
        /// </summary>
        private void CreateNode_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            CreateNode();
        }

        /// <summary>
        /// Creates a new node in the network at the current mouse location.
        /// </summary>
        private void CreateNode()
        {
            var newNodePosition = Mouse.GetPosition(networkControl);

            this.ViewModel.CreateLogicNode(newNodePosition.X, newNodePosition.Y);
        }

        /// <summary>
        /// Event raised to delete the selected node.
        /// </summary>
        private void DeleteSelectedNodes_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            this.ViewModel.DeleteSelectedNodes();
        }

        /// <summary>
        /// Add node with Enter
        /// </summary>
        private void EnterCreateNode_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            if (!isSummerEditor)
                this.ViewModel.EnterCreateNodeLogic();

        }

        /// <summary>
        /// Event raised to delete a connection.
        /// </summary>
        private void DeleteConnection_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            var connection = (ConnectionViewModel)e.Parameter;
            this.ViewModel.DeleteConnection(connection);
        }

        /// <summary>
        /// Event raised to delete a node.
        /// </summary>
        private void DeleteNode_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            var node = (NodeViewModel)e.Parameter;
            this.ViewModel.DeleteNode(node);
        }

        /// <summary>
        /// insert node when press Insert Button
        /// </summary>
        private void InsertCreateNode_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            if(!isSummerEditor)
                ViewModel.InsertNodeLogic();
        }


        /// <summary>
        /// Event raised to expan a node.
        /// </summary>
        private void ExpanNode_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            var node = (NodeViewModel)e.Parameter;
            this.ViewModel.ExpanChildNode(node);
        }

        /// <summary>
        /// Event raised when the size of a node has changed.
        /// </summary>
        private void Node_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            //
            // The size of a node, as determined in the UI by the node's data-template,
            // has changed.  Push the size of the node through to the view-model.
            //
            var element = (FrameworkElement)sender;
            var node = (NodeViewModel)element.DataContext;
            node.Size = new Size(element.ActualWidth, element.ActualHeight);
        }

       

        private void AdornedControl_MouseUp(object sender, MouseButtonEventArgs e)
        {
            try
            {
                AdornedControl.AdornedControl control = ((AdornedControl.AdornedControl)sender);
                string name = (control.AdornerContent.DataContext as NodeViewModel).Name;
                detailView.SetContain(currentMindmap.GetNodeByName(name));

            }
            catch { }            

        }

        bool isDropOnItem = false;
        private void networkControl_Drop(object sender, DragEventArgs e)
        {
            if (!isDropOnItem)
            {
                TreeViewItemWithIcons item = e.Data.GetData("LuanVanProject.TreeViewItemWithIcons") as TreeViewItemWithIcons;
                if (item != null)
                {
                    Node node = (item.Tag as TreeViewItemWithIcons.TreeViewTag).node;

                    Point mouse = e.GetPosition(this.zoomAndPanControl);
                    if (ViewModel.CheckNodeExist(node.Name) == null)
                    {
                        this.AddNodeToEditor(node, mouse.X, mouse.Y);
                        this.ViewModel.AddCommandAdd(node);
                        App.Synchronize();
                    }
                }
            }
            else
            {
                isDropOnItem = false;
            }

        }

        private void AdornedControl_Drop(object sender, DragEventArgs e)
        {
            if (this.isSummerEditor)
            {
                TreeViewItemWithIcons item = e.Data.GetData("LuanVanProject.TreeViewItemWithIcons") as TreeViewItemWithIcons;
                Node node = (item.Tag as TreeViewItemWithIcons.TreeViewTag).node;
                NodeViewModel parent =(sender as AdornedControl.AdornedControl).DataContext as NodeViewModel;         
                if (ViewModel.CheckNodeExist(node.Name) == null)
                {
                    Node nodetem = new Node(node);
                    ViewModel.ConnecteNodeLogic(nodetem, parent);
                    ViewModel.AddCommandAdd(nodetem);
                }
                isDropOnItem = true;
            }
        }

        //public void DelectNodeAndChildren(NodeViewModel _node)
        //{
        //    ViewModel.DeleteNodesAndChildren(_node);
        //}


        NodeViewModel currentTextChangeNode = null;
        TextBox currentTextBox = null;
       

        private void TextBox_LostFocus(object sender, RoutedEventArgs e)
        {
            Color clor = new Color();
            clor.A = 0;
            
            TextBox textBox = sender as TextBox;
            textBox.Background = new SolidColorBrush(clor);
            NodeViewModel node = textBox.DataContext as NodeViewModel;
            if (node != null)
            {
                node.IsSelected = false;
               node.IsTextChange = false;
                currentTextChangeNode = null;
                currentTextBox = null;
            }
           // this.ViewModel.Update();
        }


        private void networkControl_NodeDragging(object sender, NodeDraggingEventArgs e)
        {

        }

        private void networkControl_NodeDragCompleted(object sender, NodeDragCompletedEventArgs e)
        {
            if (e.Nodes.Count == 1)
            {
                //this.ViewModel.NodeDragCompleted(e);
                NodeViewModel dest = null;
                foreach (NodeViewModel node in e.nodes)
                {
                    dest = node;
                }
                this.ViewModel.NodeDragCompleted(dest);

            }
            
        }



        private void TextBox_KeyUp(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Return)
            {
                TextBox texbox = sender as TextBox;
                SaveTextBox(texbox);
            }
        }

        private  void SaveTextBox(TextBox texbox)
        {
            if (texbox != null)
            {
                NodeViewModel node = texbox.DataContext as NodeViewModel;
                if (node != null)
                {                    
                    node.NodeData.Name = texbox.Text;
                    ViewModel.CheckAndChange(node.NodeData,false);
                    currentTextChangeNode = null;
                    //ViewModel.Update();
                    App.Synchronize();
                }
            }
        }

        private void DeleteSelectedNodes_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {            
            if (this.ViewModel.CountSelectedNode() > 0)
            {
                e.CanExecute = true;                
            }
        }

        private void InsertCreateNode_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            if (this.ViewModel.CountSelectedNode() == 1)
            {
                e.CanExecute = true;
                
            }
        }

        private void AdornedControl_MouseDown(object sender, MouseButtonEventArgs e)
        {
            
            TextBox textbox = (((sender as AdornedControl.AdornedControl).Content as Grid).Children[1] as Grid).Children[0]  as TextBox;
            //FocusManager.SetFocusedElement(networkControl, textbox);
            (sender as AdornedControl.AdornedControl).Focusable = true;
            (sender as AdornedControl.AdornedControl).Focus();
            //textbox.Focus();
            if (currentTextChangeNode != null && currentTextChangeNode.Name.Equals(textbox.Text.Trim()))
            {
                currentTextChangeNode.IsTextChange = false;
                currentTextChangeNode.IsSelected = false;
                Color clor = new Color();
                clor.A = 0;
                currentTextBox.Background = new SolidColorBrush(clor);
                
                SaveTextBox(currentTextBox);
            }
            textbox.Focusable = true;
            if (currentTextChangeNode == null)
            {
                //FocusManager.SetFocusedElement(
                //(sender as AdornedControl.AdornedControl).Focus();
                //textbox.SelectionLength = textbox.Text.Length;
            }
            
            
        }

        private void Export_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            string name = (this.Parent as DocumentContent).Title + ".pptx";
            ExportConfig exportWindow = new ExportConfig(ViewModel.ViewNode, name);
            exportWindow.ShowDialog();
        }

        private void ViewInMindmap_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            
            
            NodeViewModel node = ViewModel.GetFirstSelectedNode();
            if (node != null)
            {
                MindmapEditor editor = new MindmapEditor();
                DocumentContent itemDock = new DocumentContent();
                itemDock.Title = "[Mindmap] " + node.Name;
                itemDock.Content = editor;

                App.DockPane.Items.Add(itemDock);
                editor.LoadData(node.NodeData);
                App.observerList.Add(editor);
            }
        }

        private void ViewInMindmap_CanExecuted(object sender, CanExecuteRoutedEventArgs e)
        {
            if (this.ViewModel.CountSelectedNode() == 1)
            {
                e.CanExecute = true;
            }
        }

        private void UpButton_Click(object sender, RoutedEventArgs e)
        {
            Node node = (((sender as Button).Parent as Grid).DataContext as NodeViewModel).NodeData;
            node.Up();
            App.Synchronize();
        }

        private void DownButton_Click(object sender, RoutedEventArgs e)
        {
            Node node = (((sender as Button).Parent as Grid).DataContext as NodeViewModel).NodeData;
            node.Down();
            App.Synchronize();
        }

       

        private void Back_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            this.ViewModel.Back();
            
        }

        private void Next_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            this.ViewModel.Next();
            App.Synchronize();
        }
        
        List<NodeError> SearchError(Node n, List<NodeError> list)
        {
            if (n.ErrorList != null)
            {
                foreach (int error in n.ErrorList)
                {
                    NodeError nodeError = new NodeError();
                    nodeError.index = 0;
                    nodeError.nodeName = n.Name;
                    nodeError.errorType = ErrorTypesHelper.GetInstance().GetErrorTypeByID(error);
                    list.Add(nodeError);
                }
            }
                foreach (Node child in n.ChildrenNodeList)
                {
                    SearchError(child, list);
                }
            return list;
        }
        private void Scan_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            List<NodeError> list = new List<NodeError>();
            SearchError(this.currentMindmap.RootNode, list);
            App.ErrorPanel.ViewError(list);               
        }

        private bool IsLetterOrDigit(Key key)
        {
            if (key.ToString().Length == 1)
            {
                char ch = (char)key.ToString()[0];
                if (char.IsLetterOrDigit(ch))
                    return true;

            }
            return false;
        }
        private void AdornedControl_KeyDown(object sender, KeyEventArgs e)
        {
            
            if (IsLetterOrDigit(e.Key))
            {
                TextBox textBox = (((sender as AdornedControl.AdornedControl).Content as Grid).Children[1] as Grid).Children[0] as TextBox;
                
                NodeViewModel node = textBox.DataContext as NodeViewModel;
                if (node != null && !node.IsTextChange )
                {
                        this.networkControl.SelectedNodes.Clear();

                        node.IsSelected = true;
                        node.IsTextChange = true;

                        currentTextChangeNode = node;
                        textBox.Background = Brushes.White;
                    
                        currentTextBox = textBox;
                        currentTextBox.Focusable = true;
                        currentTextBox.Focus();
                        //currentTextBox.Text = e.Key.ToString();               
                }
            }
            //textBox.SelectionLength = textBox.Text.Length;
        }


        private void TextBox_GotFocus(object sender, RoutedEventArgs e)
        {
            TextBox textBox = sender as TextBox;
            
            NodeViewModel node = textBox.DataContext as NodeViewModel;
            if (node != null)
            {
                this.networkControl.SelectedNodes.Clear();

                if (currentTextChangeNode != null && !currentTextChangeNode.Name.Equals(node.Name))
                {
                    currentTextChangeNode.IsTextChange = false;
                    currentTextChangeNode.IsSelected = false;
                    Color clor = new Color();
                    clor.A = 0;
                    currentTextBox.Background = new SolidColorBrush(clor);

                    SaveTextBox(currentTextBox);
                }
                node.IsSelected = true;
                node.IsTextChange = true;

                currentTextChangeNode = node;
                currentTextBox = textBox;

            }
            textBox.Background = Brushes.White;
            textBox.SelectionLength = textBox.Text.Length;
            //this.ViewModel.Update();
        }

        public static T FindChild<T>(DependencyObject parent, string childName)
   where T : DependencyObject
        {
            // Confirm parent and childName are valid. 
            if (parent == null) return null;

            T foundChild = null;

            int childrenCount = VisualTreeHelper.GetChildrenCount(parent);
            for (int i = 0; i < childrenCount; i++)
            {
                var child = VisualTreeHelper.GetChild(parent, i);
                // If the child is not of the request child type child
                T childType = child as T;
                if (childType == null)
                {
                    // recursively drill down the tree
                    foundChild = FindChild<T>(child, childName);

                    // If the child is found, break so we do not overwrite the found child. 
                    if (foundChild != null) break;
                }
                else if (!string.IsNullOrEmpty(childName))
                {
                    var frameworkElement = child as FrameworkElement;
                    // If the child's name is set for search
                    if (frameworkElement != null && frameworkElement.Name == childName)
                    {
                        // if the child's name is of the request name
                        foundChild = (T)child;
                        break;
                    }
                }
                else
                {
                    // child element found.
                    foundChild = (T)child;
                    break;
                }
            }

            return foundChild;
        }
        private void networkControl_KeyDown(object sender, KeyEventArgs e)
        {
            
            if (IsLetterOrDigit(e.Key))
            {
                NodeViewModel selectedItem = (sender as NetworkView).GetSelectedUIItem() as NodeViewModel;
                if(selectedItem != null && currentTextChangeNode == null)
                {
                    string textBoxName = StringProcess(selectedItem.Name);
                    TextBox textBox = FindChild<TextBox>(networkControl, textBoxName);
                    if (textBox != null)
                    {
                        selectedItem.IsSelected = true;
                        selectedItem.IsTextChange = true;

                        currentTextChangeNode = selectedItem;
                        textBox.Background = Brushes.White;

                        currentTextBox = textBox;
                        currentTextBox.Focusable = true;
                        currentTextBox.Focus();
                    }
                }
            }
        }

        private void TextBox_Loaded(object sender, RoutedEventArgs e)
        {
            TextBox textBox = sender as TextBox;
            textBox.Name = StringProcess(textBox.Text.Trim());
        }

       

        private  string StringProcess(string s)
        {
            string finalString = "";
            string rs = s.Replace(" ", "");
            Regex regex = new Regex("\\p{IsCombiningDiacriticalMarks}+");
            string temp = rs.Normalize(NormalizationForm.FormD);
            temp = regex.Replace(temp, String.Empty).Replace('\u0111', 'd').Replace('\u0110', 'D');
            for(int i = 0;i<temp.Length;i++)
            {
                if (char.IsLetterOrDigit((char)temp[i]))
                {
                    finalString += temp[i];
                }
            }
            return finalString;
        }

        private void Import_Executed(object sender, ExecutedRoutedEventArgs e)
        {

            System.Windows.Forms.OpenFileDialog openDlg = new System.Windows.Forms.OpenFileDialog();
            openDlg.Multiselect = false;
            openDlg.Filter = "Supported Files(PPT;PPTX)|*.PPTX;*.PPT";
            if (openDlg.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                Node importNode = ViewModel.GetFirstSelectedNode().NodeData;
                ProcessDlg processDlg = new ProcessDlg(importNode,openDlg.FileName,currentMindmap,ViewModel);
                processDlg.ShowDialog();
            }
            
        }

        private void Import_CanExecuted(object sender, CanExecuteRoutedEventArgs e)
        {
            if (this.ViewModel.CountSelectedNode() == 1)
            {
                e.CanExecute = true;
            }
        }  

    }
}
